package biblioteca.model;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import com.mysql.jdbc.PreparedStatement;
import biblioteca.controller.ItemIndisponivelException;
import biblioteca.controller.ItemNaoEncontradoException;

/**
 * Classe responsavel pela modelagem da Biblioteca, bem como executa as acoes de buscarItem,
 * listar todo o acervo, alugar um ItemAcervo e receber um ItemAcervo.
 * 
 * @author willen leiros, e fabio queiroz
 */
public class Biblioteca {
	
	private String nomeBiblioteca;
	Acervo acervo;
	private Connection connection;
	private PreparedStatement stmt;
	GerenciarAcervo CRUD = new GerenciarAcervo();
	
	/**
	 * Construtor que instancia uma conexao com o Banco de Dados e inicializa o Acervo.
	 * @param nome Parametro do tipo String que representa o nome da Biblioteca.
	 */
	public Biblioteca(String nome){
		nomeBiblioteca = nome;
		acervo = new Acervo();
		this.connection = new ConnectionFactory().getConnection();
	}
	
	/**
	 * Esse metodo e responsavel por buscar pelo titulo um item no Acervo de Itens.
	 * @param titulo Parametro do tipo String que representa o titulo do ItemAcervo.
	 * @return ItemAcervo
	 * @throws ItemNaoEncontradoException Lanca uma mensagem de erro quando o ItemAcervo nao e localizado.
	 * @throws ItemIndisponivelException Lanca uma mensagem de erro qundo o ItemAcervo esta indisponivel (Locado).
	 */
	
	public ItemAcervo buscarItem(String titulo) 
					throws ItemNaoEncontradoException, ItemIndisponivelException{
		return acervo.getItem(titulo);
	}
	
	/**
	 * Esse metodo e responsavel por buscar pelo codigo um item no Acervo de itens. 
	 * @param codItem Parametro do tipo inteiro que representa o codigo do ItemAcervo.
	 * @return ItemAcervo
	 * @throws ItemNaoEncontradoException Lanca uma mensagem de erro quando o ItemAcervo nao e encontrado.
	 */
	
	public ItemAcervo buscarItem(int codItem) 
					throws ItemNaoEncontradoException{
		return acervo.getItem(codItem);
	}
	

	/**
	 * Esse metodo retorna a lista de itens do Acervo de Itens
	 * @return  itens
	 * 
	 */
	
	public ArrayList<ItemAcervo> listarAcervo(){
		return CRUD.listarItens();
	}
	
	/**
	 * Esse metodo e responsavel por registrar a locacao no Banco de Dados, gerando a data do aluguel
	 * e a data de devolucao.
	 * 
	 * @param item Parametro do tipo ItemAcervo. Representa um objeto item. 
	 * @param usuario Parametro do tipo Usuario. Representa um objeto usuario.
	 * @param locacao Parametro do tipo Locacao. Representa um objeto locacao.
	 */
	
	public void alugar(ItemAcervo item, Usuario usuario, Locacao locacao){
		
		try {

			Date data1 = new Date();
			
			String dataAluguel;
			String dataDevolucao;
			
			
			SimpleDateFormat formatadorDataAluguel = new SimpleDateFormat("yyyy-MM-dd");
			dataAluguel = formatadorDataAluguel.format(data1);
			
			
			Calendar calendar = Calendar.getInstance();  
			calendar.setTime(data1);  
			calendar.add(Calendar.DAY_OF_MONTH, 10);
			Date data2 = calendar.getTime();
			SimpleDateFormat formatadorDataDevolucao = new SimpleDateFormat("yyyy-MM-dd");
			dataDevolucao = formatadorDataDevolucao.format(data2);
			
			locacao.setItem(item);
			locacao.setUsuario(usuario);
			locacao.setDataAluguel(dataAluguel);
			locacao.setDataDevolucao(dataDevolucao);
			locacao.setCusto(0);
			
			String sql1 = "insert into Leiros01.Locacao " + "(Item_codItem,Item_Acervo_codAcervo,Usuario_codUsuario,dataAluguel,dataDevolucao,dataEntrega,custo)"
					+ " values (?,?,?,?,?,?,?)";
			
			String sql2 = "update Leiros01.Item set situacao = 'Indisponivel' where codItem = " + "\'"+item.getCodItem()+"\'";
			
			stmt = (PreparedStatement) connection
					.prepareStatement(sql1);

			
			stmt.setInt(1, (int) locacao.getItem().getCodItem());
			stmt.setInt(2, 1);
			stmt.setInt(3, locacao.getUsuario().getCodUsuario());
			stmt.setString(4, locacao.getDataAluguel());
			stmt.setString(5, locacao.getDataDevolucao());
			stmt.setString(6, null);
			stmt.setDouble(7, 0);


			stmt.execute();

			stmt.executeUpdate(sql2);
			
			stmt.close();

		} 
		catch (SQLException e) {
			throw new RuntimeException(e);
		}
		  
	}
	
	/**
	 * Esse metodo registra a devolucao do ItemAcervo, calcula o valor da multa,
	 * caso o item tenha sido entregue atrasado, inseri no Banco de Dados a data
	 * de entrega e o custo.  
	 * @param item Parametro do tipo ItemAcervo. Representa um objeto item.
	 * @param usuario Parametro do tipo Usuario. Representa um objeto usuario.
	 * @param locacao Parametro do tipo Locacao. Representa um objeto locacao.
	 * @return custo
	 */
	
	
	public double devolver(ItemAcervo item, Usuario usuario, Locacao locacao){
		
		try {
			
			int diferenca = -1;
			
			stmt = (PreparedStatement) this.connection
			.prepareStatement(" select "
						+ 	  "		dataDevolucao, dataAluguel, dataEntrega, datediff(curdate(),dataAluguel) diferenca "
						+ "		from "
						+ "			Leiros01.Locacao "
						+ "		where "
						+ "			Item_codItem = "+item.getCodItem()+""
						+ "		and "
						+ "			Item_Acervo_codAcervo = 1"
						+ "		and "
						+ "			Usuario_codUsuario = "+ "\'"+usuario.getCodUsuario()+"\'");
			
			ResultSet rs = stmt.executeQuery();

			while (rs.next()) {
				diferenca = rs.getInt("diferenca");
				locacao.setDataEntrega(rs.getString("dataEntrega"));
			}
			
			if (diferenca > 10){
				locacao.setCusto((diferenca - 10) * 2.5);//Calcula a multa
			}
			
			if (locacao.getDataEntrega() == null){//Verifica se o item já foi locado
				
				String sql1 = " update Leiros01.Locacao "
						+ "		set "
						+ "			dataEntrega = current_date, "
						+ "			custo = "+ locacao.getCusto() +" "
						+ "		where "
						+ "			Item_codItem = " + "\'"+item.getCodItem()+"\'"
						+ "		and"
						+ "			Item_Acervo_codAcervo = 1"
						+ "		and "
						+ "			Usuario_codUsuario = "+ "\'"+usuario.getCodUsuario()+"\'";
				
				stmt.executeUpdate(sql1);
				
				String sql2 = "update Leiros01.Item set situacao = 'Disponivel' where codItem = " + "\'"+item.getCodItem()+"\'";
				
				stmt.executeUpdate(sql2);
			}
			
			rs.close();
			stmt.close();
			
			return locacao.getCusto();
		} 
		catch (SQLException e) {
			throw new RuntimeException(e);
		}
	}
	
	
	/**
	 * Esse metodo retorna o nome da Biblioteca.
	 * @return nomeBiblioteca
	 */
	public String getNomeBiblioteca() {
		return nomeBiblioteca;
	}	
}
